#pragma once

#include "Connection.hpp"
#include "InetAddr.hpp"

#include <string>

#define BUF_SIZE 1024

class Channel : public Connection       // 普通连接对象
{
    static const int size = 1024;
    
public:

    Channel(int sockfd, const InetAddr& client)
        :_client(client)
        ,_sockfd(sockfd)
    {
        setNonBlock(sockfd);
    }

    void recver() override
    {
        char buf[BUF_SIZE];
        while (true)
        {
            int n = recv(_sockfd, buf, sizeof(buf) - 1, 0);
            if (n > 0)
            {
                buf[n] = 0;
                _inbuf += buf;
            }
            else if (n == 0)
            {
                excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    excepter();
                    return;
                }
            }
        }

        LOG(LogLevel::DEBUG) << "channel inbuf:" << _inbuf;

        if (_inbuf.empty() == false)
        {
            _outbuf += _handler(_inbuf);
        }

        if (_outbuf.empty() == false)
        {
            sender();
        }
    }    
    
    void sender() override
    {
        while (true)
        {
            int n = send(_sockfd, _outbuf.c_str(), _outbuf.size(), 0);
            if (n > 0)
            {
                _outbuf.erase(0, n);
                if (_outbuf.empty())
                {
                    break;
                }
            }
            else if (n == 0)
            {
                return;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    excepter();
                    return;
                }
            }
        }

        if (_outbuf.empty() == false)   // 当输出字符串不为空时，需要关系写事件将资源输出
        {
            getOwner()->enableReadWrite(_sockfd, true, true);   // 读、写事件都关系
        }
        else
        {
            getOwner()->enableReadWrite(_sockfd, true, false);  // 只关系读事件
        }
    }

    void excepter() override
    {
        getOwner()->delConnection(_sockfd);
    }

    int getSockfd() override
    {
        return _sockfd;
    }

    const std::string& getInbuffer() const
    {
        return _inbuf;
    }

    void appendOutbuffer(const std::string& str)
    {
        _outbuf += str;
    }

    ~Channel()
    {
        ;
    }
    
private:

    int _sockfd;
    std::string _inbuf;
    std::string _outbuf;
    InetAddr _client;
};
